package com.idp.system.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.idp.common.constants.ElasticSearchIndexConstant;
import com.idp.common.error.SystemException;
import com.idp.common.model.LoginInfo;
import com.idp.common.model.PageModel;
import com.idp.common.utils.ContextUtil;
import com.idp.system.dto.SysLogDto;
import com.idp.system.dto.SysLogSearchDto;
import com.idp.system.entity.SysLogEntity;
import com.idp.system.mapper.SysLogMapper;
import com.idp.system.service.SysLogService;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 系统日志Service实现类
 * @author King
 */
@Service
public class SysLogServiceImpl implements SysLogService {

	private static final Logger log = LoggerFactory.getLogger(SysLogServiceImpl.class);

	@Autowired
	private SysLogMapper sysLogMapper;
	@Autowired
	private RestHighLevelClient restHighLevelClient;

	@Override
	public PageModel<SysLogDto> findByPage(SysLogSearchDto sysLogSearchDto) {

		if(sysLogSearchDto.getOperateTimeEnd() != null) {
			sysLogSearchDto.setOperateTimeEnd(DateUtil.endOfDay(sysLogSearchDto.getOperateTimeEnd()));
		}

		PageModel<SysLogDto> page = new PageModel<SysLogDto>();
		page.setList(sysLogMapper.getList(sysLogSearchDto));
		return page;

//		return this.findByES(sysLogSearchDto, page);
	}

	private PageModel<SysLogDto> findByES(SysLogSearchDto sysLogSearchDto, PageModel<SysLogDto> page) {

		BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
		queryBuilder.must(QueryBuilders.matchAllQuery());

		if(StrUtil.isNotEmpty(sysLogSearchDto.getOperateType())) {
			queryBuilder.filter(QueryBuilders.termsQuery("operateType", sysLogSearchDto.getOperateType()));
		}
		if(StrUtil.isNotEmpty(sysLogSearchDto.getInterfaceUrl())) {
			queryBuilder.filter(QueryBuilders.matchQuery("interfaceUrl", sysLogSearchDto.getInterfaceUrl()));
		}
		if(StrUtil.isNotEmpty(sysLogSearchDto.getOperateUserName())) {
			queryBuilder.filter(QueryBuilders.matchQuery("operateUser", sysLogSearchDto.getOperateUserName()));
		}
		if(sysLogSearchDto.getOperateTimeStart() != null) {
			String startTime = DateUtil.formatDateTime(sysLogSearchDto.getOperateTimeStart());
			queryBuilder.filter(QueryBuilders.rangeQuery("operateTime.keyword").gte(startTime));
		}
		if(sysLogSearchDto.getOperateTimeEnd() != null) {
			String endTime = DateUtil.formatDateTime(sysLogSearchDto.getOperateTimeEnd());
			queryBuilder.filter(QueryBuilders.rangeQuery("operateTime.keyword").lte(endTime));
		}

		try {

			SearchRequest request = new SearchRequest(ElasticSearchIndexConstant.SYS_LOG);
			request.source().query(queryBuilder)
					.sort("operateTime.keyword", SortOrder.DESC)
					.from((page.getPage() - 1) * page.getRows())
					.size(page.getRows());
			SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);
			SearchHits searchHits = searchResponse.getHits();
			long total = searchHits.getTotalHits().value;
			SearchHit[] hits = searchHits.getHits();
			List<SysLogDto> sysLogDtoList = new ArrayList<>();

			for(SearchHit hit : hits) {
				String json = hit.getSourceAsString();
				SysLogDto sysLogDto = JSON.parseObject(json, SysLogDto.class);
				sysLogDto.setId(hit.getId());
				sysLogDtoList.add(sysLogDto);
			}

			page.setResultData(sysLogDtoList, total);

		} catch (IOException e) {
			log.error("doc分页查询异常:{} ", e);
			throw new SystemException("分页查询失败");
		}

		return page;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveLog(String url, String params, String response, Date startTime) {

		SysLogEntity logEntity = new SysLogEntity();
		logEntity.setInterfaceUrl(url);
		logEntity.setInterfaceParam(params);
		logEntity.setInterfaceResponse(response);
		logEntity.setOperateTime(startTime);
		logEntity.setResponseTime(new Date());

		LoginInfo loginInfo = ContextUtil.getLoginUser();

		if(loginInfo != null) {
			logEntity.setOperateUser(loginInfo.getId());
			logEntity.setOperateType(loginInfo.getUserType());

			log.info(JSONUtil.toJsonStr(logEntity));

			sysLogMapper.insert(logEntity);

//			try {
//				// 保存到es中
//				IndexRequest indexRequest = new IndexRequest(ElasticSearchIndexConstants.SYS_LOG);
//				indexRequest.id(IdUtil.simpleUUID());
//				indexRequest.source(JSON.toJSONString(logEntity), XContentType.JSON);
//				restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
//			} catch (IOException e) {
//				log.error(e.getMessage(), e);
//				throw new SystemException("ES保存数据失败");
//			}
		}
	}

}
